/*=====================================================================================================================
                    Copyright(c) 2005 Geometric PLM Software Corp. All rights reserved.
                             Unpublished - All rights reserved
=======================================================================================================================
File description:
    Filename: tc_aom.c
    Module  : (geometric) itk module.

        This file manages the operations of the application object module.

=======================================================================================================================
Date               Name              Description of Change
14-Jul-2009        Penn,Xie          Initialize creation
$HISTORY$
=====================================================================================================================*/
#ifdef BUILD_IMAN 
#include <iman_string.h>
#include <imantype.h>
#include <iman_util.h>

#define  GTC_strcmp                     iman_strcmp
#define  GTC_strcat                     iman_strcat
#define  GTC_strlen                     iman_strlen
#define  GTCTYPE_ask_object_type        IMANTYPE_ask_object_type
#define  GTCTYPE_find_type              IMANTYPE_find_type
#define  GTCTYPE_list_properties        IMANTYPE_list_properties

#else // Teamcenter
#include <fclasses\tc_string.h>
#include <tccore\tctype.h>
#include <tc\tc_util.h>

#define  GTC_strcmp                     tc_strcmp
#define  GTC_strcat                     tc_strcat
#define  GTC_strlen                     tc_strlen
#define  GTCTYPE_ask_object_type        TCTYPE_ask_object_type
#define  GTCTYPE_find_type              TCTYPE_find_type
#define  GTCTYPE_list_properties        TCTYPE_list_properties

#endif

#include <property\prop.h>
#include <tccore\aom.h>
#include <string.h>
#include <tccore\aom_prop.h>
#include <property\prop_errors.h>
#include <ai\sample_err.h>
#include <form\formtype.h>

#include "tc_type.h"
#include "string_utils.h"
#include "tc_aom.h"

int GAOM_get_attr_value( tag_t objectTag, const char *propName, char **value )
{
    int     ifail            = ITK_ok;

    char*   valueTypeName    = NULL;
    PROP_value_type_t pvtype = PROP_untyped;

    *value = NULL;

    ifail = AOM_ask_value_type( objectTag, propName, &pvtype, &valueTypeName );
    if (ifail != ITK_ok)
        return ifail;
    MEM_free( valueTypeName );

    // Get the property type of the object.
    // FIXME: Check all type rules?
    if (pvtype == PROP_string )
    {
        ifail = AOM_ask_value_string( objectTag, propName, value );
    }
    else if (pvtype == PROP_logical)
    {
        logical lValue = false;
        ifail = AOM_ask_value_logical( objectTag, propName, &lValue ) ;
        if (ifail == ITK_ok)
        {
            GSTR_int_to_string( value, lValue ? 1 : 0 );
        }
    }
    else if (pvtype == PROP_int)
    {
        int iValue = 0;
        ifail = AOM_ask_value_int( objectTag, propName, &iValue );
        if (ifail == ITK_ok)
        {
            GSTR_int_to_string( value, iValue );
        }
    }
//     else if (pvtype == PROP_char)
//     {
//         char cValue;
//         ifail = AOM_ask_value_char( objectTag, propName, &cValue );
//         if (ifail == ITK_ok)
//         {
//             
//         }
//     }
//     else if (pvtype == PROP_double)
//     {
//     }
//     else if (pvtype == PROP_date)
//     {
//     }
//     else if (pvtype == PROP_float)
//     {
//     }
//     else if (pvtype == PROP_short)
//     {
//     }
//     else if (pvtype == PROP_note)//long string
//     {
//     }
    else 
        ifail = PROP_invalid_prop_type;

    return ifail;
}

int GAOM_get_UIF_attr_value( tag_t objectTag, const char *propName, char **value )
{
    int     ifail            = ITK_ok;

    char*   valueTypeName    = NULL;
    PROP_value_type_t pvtype = PROP_untyped;

    *value = NULL;

    ifail = AOM_ask_value_type( objectTag, propName, &pvtype, &valueTypeName );
    if (ifail != ITK_ok)
        return ifail;
    MEM_free( valueTypeName );

    ifail = AOM_UIF_ask_value( objectTag, propName, value );

    return ifail;
}

int GAOM_get_UIF_attr_value_with_itemtag( tag_t objectTag, const char *propName, char **value )
{
    int     ifail            = ITK_ok;

    char*   valueTypeName    = NULL;
    PROP_value_type_t pvtype = PROP_untyped;
    int     maxElm           = 0;
    const char *SEPARATOR    = ",";
    int     i                = 0;
    logical isType           = false;

    *value = NULL;

    ifail = AOM_ask_value_type( objectTag, propName, &pvtype, &valueTypeName );
    if (ifail != ITK_ok)
        return ifail;
    MEM_free( valueTypeName );
    ifail = AOM_ask_max_num_elements( objectTag, propName, &maxElm );
    CALL( ifail );

    // Get the property type of the object.
    if (pvtype == PROP_typed_reference )
    {
        tag_t valueTag      = NULLTAG;
        int   numTag        = 0;
        tag_t *arrValueTags = NULL;     /* F */
        char  *propValue    = NULL;     /* F */
        char  propContent[POM_MAX_MAX_STRING_LENGTH * 2] = "";
        if (maxElm == 1) // Single value
        {
            ifail = AOM_ask_value_tag( objectTag, propName, &valueTag );
            if (ifail == ITK_ok && valueTag != NULLTAG)
            {
                if ( GTCTYPE_is_type_of(valueTag, "WorkspaceObject", &isType) == ITK_ok && isType )
                {
                    ifail = AOM_ask_value_string( valueTag, "object_name", value );
                }
            }
        }
        else // list
        {
            ifail = AOM_ask_value_tags( objectTag, propName, &numTag, &arrValueTags );
            if (ifail == ITK_ok && numTag != 0)
            {
                for (i = 0; (i < numTag && ifail == ITK_ok); i++)
                {
                    if ( GTCTYPE_is_type_of(valueTag, "WorkspaceObject", &isType) == ITK_ok && isType )
                    {
                        ifail = AOM_ask_value_string( arrValueTags[i], "object_name", &propValue );
                    }
                    if (ifail == ITK_ok && propValue != NULL)
                    {
                        if (i != 0)
                            GTC_strcat( propContent, SEPARATOR );
                        GTC_strcat( propContent, propValue );
                    }
                    MEM_free( propValue );
                    propValue = NULL;
                }

                //
                GSTR_clone( value, propContent );
                MEM_free( arrValueTags );
            }
        }
    }
    else 
    {
        ifail = AOM_UIF_ask_value( objectTag, propName, value );
    }

    return ifail;
}


logical GAOM_is_attr_exist( tag_t objectTag, const char *propName )
{
    logical bFind       = false;

    int     i           = 0;
    int     ifail       = ITK_ok;
    int     propCnt     = 0;
    char    **propNames = NULL;

    ifail = AOM_ask_prop_names( objectTag, &propCnt, &propNames );
    if (ifail != ITK_ok)
        return false;

    for ( i = 0; i < propCnt; i++ )
    {
        if ( GTC_strcmp( propNames[i], propName ) == 0)
        {
            bFind = true;
            break;
        }
    }

    MEM_free( propNames );

    return bFind;
}

int GAOM_ask_form_prop_names( tag_t objectTag, int *propCount, char ***propNames )
{
    int   ifail         = ITK_ok;

    int   i             = 0;
    char  *stroeCName   = NULL;
    tag_t typeTag       = NULLTAG;
    tag_t storeTypeTag  = NULLTAG;
    tag_t *attIds       = NULLTAG;

    *propCount = 0;
    *propNames = NULL;

    if ((ifail = GTCTYPE_ask_object_type( objectTag, &typeTag )) == ITK_ok 
        && (ifail = FORMTYPE_ask_def_class_name( typeTag, &stroeCName )) == ITK_ok
        && (ifail = GTCTYPE_find_type(NULL, stroeCName, &storeTypeTag )) == ITK_ok 
        && storeTypeTag != NULLTAG
        && (ifail = GTCTYPE_list_properties( storeTypeTag, propCount, &attIds )) == ITK_ok )
    {
        *propNames = (char**)MEM_alloc( (*propCount) * sizeof(char*) );
        for ( i = 0; (i < *propCount && ifail == ITK_ok); i++ )
        {
            ifail = PROPDESC_ask_name( attIds[i], &(*propNames)[i] );
        }
        if (ifail != ITK_ok)
        {
            MEM_free( *propNames );
            *propNames = NULL;
            *propCount = 0;
        }
    }
    MEM_free( attIds );
    MEM_free( stroeCName );

    return ifail;
}

int GAOM_ask_form_class_prop_names( tag_t objectTag, int *propCount, char ***propNames )
{
    int ifail = ITK_ok;

    tag_t   formTypeTag       = NULLTAG;
    char    *storageClassName = 0;              // <F>
    char    *applicationName  = 0;              // <F>
    int     descriptor        = 0;
    tag_t   *storageAttrs     = 0;              // <F>
    tag_t   storageClass      = NULLTAG;
    int     *types            = 0;              // <F>
    int     *descriptors      = 0;              // <F>
    int     *maxStringLens    = 0;              // <F>
    tag_t   *referClasses     = 0;              // <F>
    int     *lengths          = 0;              // <F>
    int     *failures         = 0;              // <F>

    *propCount = 0;
    *propNames = NULL;

    GTCTYPE_ask_object_type( objectTag, &formTypeTag );

    ifail = FORMTYPE_ask_def_class_name( formTypeTag, &storageClassName );
    if( storageClassName == 0 || GTC_strlen( storageClassName ) == 0 )
        goto ASKCLASSPROP_EXIT;

    ifail = POM_class_id_of_class( storageClassName, &storageClass );
    if (ifail != ITK_ok)
        goto ASKCLASSPROP_EXIT;

    // -1 means "list inherited attributes"
    // like POM_describe_class( storageClass, -1, NULL, &applicationName, &descriptor, &nStorageAttrs, &storageAttrs );
    ifail = POM_describe_class( storageClass, 0, NULL, &applicationName, &descriptor, propCount, &storageAttrs );
    if (ifail != ITK_ok)
        goto ASKCLASSPROP_EXIT;

    ifail = POM_describe_attrs( storageClass, *propCount, storageAttrs, 
        propNames, &types, &maxStringLens, &referClasses, &lengths, &descriptors, &failures);

ASKCLASSPROP_EXIT:
    if (ifail != ITK_ok)
    {
        *propCount = 0;
        MEM_free( *propNames );
        *propNames = NULL;
    }
    MEM_free( storageClassName );
    MEM_free( applicationName );
    MEM_free( storageAttrs );
    MEM_free( types );
    MEM_free( descriptors );
    MEM_free( maxStringLens );
    MEM_free( referClasses );
    MEM_free( lengths );
    MEM_free( failures );

    return ifail;
}

int GAOM_copy_prop( tag_t destTag, const char *destProp, tag_t srcTag, const char *srcProp )
{
    int ifail = ITK_ok;
    char   *destTypeName       = NULL;
    PROP_value_type_t desttype = PROP_untyped;
    char   *srcTypeName        = NULL;
    PROP_value_type_t srctype  = PROP_untyped;
    char *strValue = NULL;

    AOM_lock( destTag );

    if ( (ifail = AOM_ask_value_type( destTag, destProp, &desttype, &destTypeName )) != ITK_ok
        || (ifail = AOM_ask_value_type( srcTag, srcProp, &srctype, &srcTypeName )) != ITK_ok 
        || srctype != desttype )
    {
        if (srctype != desttype)
        {
            ifail = PROP_invalid_value_type;
        }
        goto COPY_PROP_EXIT;
    }

    if ( desttype == PROP_int || desttype == PROP_short )
    {
        int  intValue  = 0;
        ifail = AOM_ask_value_int( srcTag, srcProp, &intValue );
        if (ifail == ITK_ok)
        {
            ifail = AOM_set_value_int( destTag, destProp, intValue );
        }
    }
    else if (desttype == PROP_char )
    {
        char cValue = 0;
        ifail = AOM_ask_value_char( srcTag, srcProp, &cValue );
        if (ifail == ITK_ok)
        {
            ifail = AOM_set_value_char( destTag, destProp, cValue );
        }
    }
    else if (desttype == PROP_date )
    {
        date_t dtValue;
        ifail = AOM_ask_value_date( srcTag, srcProp, &dtValue );
        if (ifail == ITK_ok)
        {
            ifail = AOM_set_value_date( destTag, destProp, dtValue );
        }
    }
    else if (desttype == PROP_double || desttype == PROP_float)
    {
        double dbValue = 0;
        ifail = AOM_ask_value_double( srcTag, srcProp, &dbValue );
        if (ifail == ITK_ok)
        {
            ifail = AOM_set_value_double( destTag, destProp, dbValue );
        }
    }
    else if (desttype == PROP_logical )
    {
        logical bValue   = 0;
        ifail = AOM_ask_value_logical( srcTag, srcProp, &bValue );
        if (ifail == ITK_ok)
        {
            ifail = AOM_set_value_logical( destTag, destProp, bValue );
        }
    }
    else if (desttype == PROP_string || desttype == PROP_note)
    {
        int maxLen = 0;
        if ( (ifail = AOM_ask_value_string( srcTag, srcProp, &strValue )) == ITK_ok 
            && (ifail = AOM_ask_max_string_length( destTag, destProp, &maxLen )) == ITK_ok )
        {
            if ( (int) GTC_strlen(strValue) > maxLen )
            {
                ifail = PROP_exceeds_array_limit;
            }
            else
                ifail = AOM_set_value_string( destTag, destProp, strValue );
        }
    }
    else
    {
        goto COPY_PROP_EXIT;
    }

    if (ifail == ITK_ok)
    {
        AOM_save( destTag );
    }
COPY_PROP_EXIT:
    AOM_unlock( destTag );
    MEM_free( strValue );
    MEM_free( destTypeName );
    MEM_free( srcTypeName );

    return ifail;
}
